package fr.bludwarf.skywarrior.ile;

import java.util.HashMap;
import java.util.TreeSet;

import fr.bludwarf.commons.StringUtils;
import fr.bludwarf.skywarrior.global.EffetsSurIle;
import fr.bludwarf.skywarrior.global.Temps;
import fr.bludwarf.skywarrior.joueur.EffetsSurTempsDeRecherche;
import fr.bludwarf.skywarrior.joueur.Ressources;
import fr.bludwarf.skywarrior.joueur.Unite;
import fr.bludwarf.skywarrior.utils.Reflect;

public class Batiment extends Unite implements EffetsSurIle, EffetsSurTempsDeRecherche, Comparable<Batiment>
{
	public static class Defense extends Batiment
	{

		public Defense(String nom, String duree, int pv, int att, int def, int coutMat, int coutEth)
		{
			super(nom, duree, new StatsCombat(pv, att, def), new Ressources(coutMat, coutEth, 0), new Ressources(0, 0, 0));
		}

	}

	// PV, coutMat
	public static final Batiment ARCHITECTE   = new Batiment("Architecte"  , "1h 15m"     , 100, 100);
	public static final Batiment ATELIER      = new Batiment("Atelier"     , "1h 52m 30s" , 100, 150);
	public static final Batiment CASERNE      = new Batiment("Caserne"     , "37m 30s"    , 100, 75);
	public static final Batiment École        = new Batiment("École"       , "1h 15m"     , 100, 100)
	{
		public double appliquerEffetsSurTempsDeRecherche(double temps)
		{
			// non-cumulable : voir Recherche.appliquerEffetsSurTempsDeRecherche
			return temps * 0.75; // Diminue les temps de recherche de 25%. (non-cumulable) 
		};
	};
	public static final Batiment TISSERAND    = new Batiment("Tisserand"   , "1h 52m 30s" , 100, 120);
	public static final Batiment TOUR_DE_GUET = new Batiment("Tour de guet", "37m 30s"    ,  50, 75);
	
	public static final Batiment Carrière   = new Batiment("Carrière"   , "3h 45m"     , null, new Ressources(100, 0, 0) , new Ressources(4, 0, 0));
	public static final Batiment CHAMPS     = new Batiment("Champs"     , "30m"        , null, new Ressources( 15, 0, 0) , new Ressources(0, 0, 2));
	public static final Batiment FERME      = new Batiment("Ferme"      , "1h 15m"     , null, new Ressources(150, 0, 0) , new Ressources(0, 0, 3));
	public static final Batiment PALAIS     = new BatimentUnique("Palais"     , 0			   , null, new Ressources(150, 0, 0) , new Ressources(7, 0, 5));
	public static final Batiment POMPE      = new Batiment("Pompe"      , "1h 15m"	   , null, new Ressources( 60, 0, 0) , new Ressources(0, 1, 0));
	public static final Batiment FONDERIE   = new Batiment("Fonderie"   , "1h 15m"	   , new StatsCombat(100, 0, 0), new Ressources( 60, 60, 0) , new Ressources(2, 0, 0));;
	public static final Batiment MOULIN     = new BatimentUnique("Moulin"     , "1h 15m"     , null, new Ressources(100, 0, 0) , new Ressources(0, 0, 0));
	public static final Batiment Université = new BatimentUnique("Université", "2h 30m", new StatsCombat(200, 0, 0), new Ressources(200, 80, 0), new Ressources(0, 0, 0))
	{
		public double appliquerEffetsSurTempsDeRecherche(double temps)
		{
			// non-cumulable : voir Recherche.appliquerEffetsSurTempsDeRecherche
			return temps * 0.6; // Diminue les temps de recherche de 40%. (non-cumulable) 
		};
	};
	
	public static final Batiment Fort       = new Batiment.Defense("Fort",     "1h 15m", 300, 60, 2, 200, 0)
	{
		public void appliquerEffetsSurIle(StatsCombat stats)
		{
			stats.add(new StatsCombat(0, 0, 4));
		};
	};
	public static final Batiment Canon        = new Batiment.Defense("Canon",        "37m 30s", 100, 20, 0,  60,   0);
	public static final Batiment Archimortier = new Batiment.Defense("Archimortier", "6h 15m" , 200,  0, 0, 900, 400);

	public static final Ressources AUCUNE_RESSOURCE = new Ressources(0, 0, 0);
	
	public static final Reflect<Batiment> REFLECT = new Reflect<Batiment>(Batiment.class);
	
	private Ressources _production;

	public Batiment(String nom, double duree, StatsCombat combat,
			Ressources cout, Ressources production)
	{
		super(nom, duree, combat, cout, 0);
		_production = production;
	}

	/**
	 * @param nom
	 * @param duree format "1h 52m 30s" (copier/coller de l'aide du site)
	 * @param combat
	 * @param cout
	 * @param production
	 */
	public Batiment(String nom, String duree, StatsCombat combat, Ressources cout,
			Ressources production)
	{
		this(nom, Temps.parseDuree(duree), combat, cout, production);
	}

	public Batiment(String nom, String duree, int pv, int coutMat)
	{
		this(nom, duree, new StatsCombat(pv, 0, 0),
		new Ressources(coutMat, 0, 0), // cout
		new Ressources(0, 0, 0)); // prod // FIXME : AUCUNE_RESSOURCE provoque un NullPointerException !!
	}

	public Ressources getProduction(EtatIle etatIle)
	{
		return _production;
	}

	public void appliquerEffetsSurIle(StatsCombat stats)
	{
		// à implémenter pour chaque bâtiment le cas échant
	}
	
	public static Batiment getBatiment(final String nom)
	{
		return REFLECT.getDeclaredField(nom);
	}

	public void appliquerEffetsSurIle(Ressources res)
	{
		// à implémenter pour chaque bâtiment le cas échant
	}

	public double appliquerEffetsSurTempsDeRecherche(double temps)
	{
		// à implémenter pour chaque bâtiment le cas échant
		return temps;
	}

	public static <T extends Comparable<T>> String toString(HashMap<T, Integer> map)
	{
		return StringUtils.join(map);
	}

	public int compareTo(Batiment o)
	{
		return this.getNom().compareTo(o.getNom());
	}

}
